package com.bsfcs.rag.service;

import com.bsfcs.rag.entity.Contract;
import com.bsfcs.rag.entity.ContractLxPlan;
import com.bsfcs.rag.entity.ContractPaymoney;
import com.bsfcs.rag.entity.Contractjxfpdj;
import com.bsfcs.rag.entity.Invoice;
import com.bsfcs.rag.entity.Project;
import com.bsfcs.rag.repository.ContractLxPlanRepository;
import com.bsfcs.rag.repository.ContractRepository;
import com.bsfcs.rag.repository.ContractjxfpdjRepository;
import com.bsfcs.rag.repository.ContractpaymoneyRepository;
import com.bsfcs.rag.repository.InvoiceRepository;
import com.bsfcs.rag.repository.ProjectRepository;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Getter;
import lombok.Setter;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ContractProjectAnalysisService {

    private final ChatClient chatClient;

    @Autowired
    private ContractRepository contractRepository;

    @Autowired
    private ContractLxPlanRepository contractLxPlanRepository;

    @Autowired
    private ContractpaymoneyRepository contractpaymoneyRepository;

    @Autowired
    private InvoiceRepository invoiceRepository;

    @Autowired
    private ContractjxfpdjRepository contractjxfpdjRepository;
    
    @Autowired
    private ProjectRepository projectRepository;
    
    @Autowired
    private ContractDataQueryConfig contractDataQueryConfig;

    ContractProjectAnalysisService(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
    }
    
    /**
     * 根据项目ID获取项目对象
     * @param projectId 项目ID
     * @return 项目对象
     */
    public Project getProjectById(String projectId) {
        return projectRepository.findById(projectId).orElse(null);
    }

    /**
     * 根据项目ID获取项目合同数据，包括合同履行节点、收款、付款、开票、回票等信息
     * @param projectId 项目ID
     * @return 项目合同数据
     */
    public ContractProjectDataDTO getProjectContractData(String projectId) {
        // 1. 根据项目ID查询项目数据
        Project project = projectRepository.findById(projectId).orElse(null);
        
        // 2. 根据项目ID查询合同数据
        List<Contract> contracts = contractRepository.findByProjectId(projectId);
        if (contracts == null || contracts.isEmpty()) {
            return null;
        }

        // 3. 获取合同ID列表
        List<String> contractIds = contracts.stream()
                .map(Contract::getId)
                .collect(Collectors.toList());

        // 4. 根据合同ID查询相关数据
        List<ContractLxPlan> contractLxPlans = contractLxPlanRepository.findByContractIdsGrouped(contractIds);
        List<ContractPaymoney> contractPaymoneys = contractpaymoneyRepository.findByContractIds(contractIds);
        List<Invoice> invoices = invoiceRepository.findByContractIdsGrouped(contractIds);
        List<Contractjxfpdj> contractjxfpdjs = contractjxfpdjRepository.findByContractIds(contractIds);

        // 5. 按合同ID对相关数据进行分组
        Map<String, List<ContractLxPlan>> lxPlansMap = contractLxPlans.stream()
                .collect(Collectors.groupingBy(ContractLxPlan::getParentID));
        Map<String, List<ContractPaymoney>> paymoneysMap = contractPaymoneys.stream()
                .collect(Collectors.groupingBy(ContractPaymoney::getContr_id_new));
        Map<String, List<Invoice>> invoicesMap = invoices.stream()
                .collect(Collectors.groupingBy(Invoice::getContr_id));
        Map<String, List<Contractjxfpdj>> jxfpdjsMap = contractjxfpdjs.stream()
                .collect(Collectors.groupingBy(Contractjxfpdj::getContract_id));

        // 6. 组装嵌套数据结构
        List<ContractProjectDataDTO.ContractDetail> contractDetails = contracts.stream()
                .map(contract -> new ContractProjectDataDTO.ContractDetail(
                        contract,
                        lxPlansMap.getOrDefault(contract.getId(), List.of()),
                        paymoneysMap.getOrDefault(contract.getId(), List.of()),
                        invoicesMap.getOrDefault(contract.getId(), List.of()),
                        jxfpdjsMap.getOrDefault(contract.getId(), List.of())
                ))
                .collect(Collectors.toList());

        // 7. 返回结果 (在构造函数中进行字段过滤)
        return new ContractProjectDataDTO(project, contractDetails, contractDataQueryConfig);
    }
    
    /**
     * 根据项目对象获取项目合同数据，包括合同履行节点、收款、付款、开票、回票等信息
     * @param projectDTO 项目对象
     * @return 项目合同数据
     */
    public ContractProjectDataDTO getProjectContractData(ProjectDTO projectDTO) {
        // 1. 根据项目ID查询合同数据
        List<Contract> contracts = contractRepository.findByProjectId(projectDTO.getId());
        if (contracts == null || contracts.isEmpty()) {
            return null;
        }

        // 2. 获取合同ID列表
        List<String> contractIds = contracts.stream()
                .map(Contract::getId)
                .collect(Collectors.toList());

        // 3. 根据合同ID查询相关数据
        List<ContractLxPlan> contractLxPlans = contractLxPlanRepository.findByContractIdsGrouped(contractIds);
        List<ContractPaymoney> contractPaymoneys = contractpaymoneyRepository.findByContractIds(contractIds);
        List<Invoice> invoices = invoiceRepository.findByContractIdsGrouped(contractIds);
        List<Contractjxfpdj> contractjxfpdjs = contractjxfpdjRepository.findByContractIds(contractIds);

        // 4. 按合同ID对相关数据进行分组
        Map<String, List<ContractLxPlan>> lxPlansMap = contractLxPlans.stream()
                .collect(Collectors.groupingBy(ContractLxPlan::getParentID));
        Map<String, List<ContractPaymoney>> paymoneysMap = contractPaymoneys.stream()
                .collect(Collectors.groupingBy(ContractPaymoney::getContr_id_new));
        Map<String, List<Invoice>> invoicesMap = invoices.stream()
                .collect(Collectors.groupingBy(Invoice::getContr_id));
        Map<String, List<Contractjxfpdj>> jxfpdjsMap = contractjxfpdjs.stream()
                .collect(Collectors.groupingBy(Contractjxfpdj::getContract_id));

        // 5. 组装嵌套数据结构
        List<ContractProjectDataDTO.ContractDetail> contractDetails = contracts.stream()
                .map(contract -> new ContractProjectDataDTO.ContractDetail(
                        contract,
                        lxPlansMap.getOrDefault(contract.getId(), List.of()),
                        paymoneysMap.getOrDefault(contract.getId(), List.of()),
                        invoicesMap.getOrDefault(contract.getId(), List.of()),
                        jxfpdjsMap.getOrDefault(contract.getId(), List.of())
                ))
                .collect(Collectors.toList());
                
        // 6. 构造Project对象
        Project project = new Project();
        project.setId(projectDTO.getId());
        project.setProject_name(projectDTO.getProject_name());
        project.setProject_code(projectDTO.getProject_code());

        // 7. 返回结果 (在构造函数中进行字段过滤)
        return new ContractProjectDataDTO(project, contractDetails, contractDataQueryConfig);
    }
    
    /**
     * 根据项目对象获取项目合同数据（以项目作为最外层结构）
     * @param project 项目对象
     * @return 项目合同数据
     */
    public ProjectContractDataDTO getProjectContractDataWithProjectAsRoot(Project project) {
        // 1. 根据项目ID查询合同数据
        List<Contract> contracts = contractRepository.findByProjectId(project.getId());
        if (contracts == null || contracts.isEmpty()) {
            return null;
        }

        // 2. 获取合同ID列表
        List<String> contractIds = contracts.stream()
                .map(Contract::getId)
                .collect(Collectors.toList());

        // 3. 根据合同ID查询相关数据
        List<ContractLxPlan> contractLxPlans = contractLxPlanRepository.findByContractIdsGrouped(contractIds);
        List<ContractPaymoney> contractPaymoneys = contractpaymoneyRepository.findByContractIds(contractIds);
        List<Invoice> invoices = invoiceRepository.findByContractIdsGrouped(contractIds);
        List<Contractjxfpdj> contractjxfpdjs = contractjxfpdjRepository.findByContractIds(contractIds);

        // 4. 按合同ID对相关数据进行分组
        Map<String, List<ContractLxPlan>> lxPlansMap = contractLxPlans.stream()
                .collect(Collectors.groupingBy(ContractLxPlan::getParentID));
        Map<String, List<ContractPaymoney>> paymoneysMap = contractPaymoneys.stream()
                .collect(Collectors.groupingBy(ContractPaymoney::getContr_id_new));
        Map<String, List<Invoice>> invoicesMap = invoices.stream()
                .collect(Collectors.groupingBy(Invoice::getContr_id));
        Map<String, List<Contractjxfpdj>> jxfpdjsMap = contractjxfpdjs.stream()
                .collect(Collectors.groupingBy(Contractjxfpdj::getContract_id));

        // 5. 组装嵌套数据结构
        List<ProjectContractDataDTO.ContractDetail> contractDetails = contracts.stream()
                .map(contract -> new ProjectContractDataDTO.ContractDetail(
                        contract,
                        lxPlansMap.getOrDefault(contract.getId(), List.of()),
                        paymoneysMap.getOrDefault(contract.getId(), List.of()),
                        invoicesMap.getOrDefault(contract.getId(), List.of()),
                        jxfpdjsMap.getOrDefault(contract.getId(), List.of())
                ))
                .collect(Collectors.toList());

        // 6. 返回结果 (在构造函数中进行字段过滤)
        return new ProjectContractDataDTO(project, contractDetails, contractDataQueryConfig);
    }
    
    /**
     * 根据项目ID获取项目合同数据（以项目作为最外层结构）
     * @param projectId 项目ID
     * @return 项目合同数据的中文字段名JSON字符串
     * @throws JsonProcessingException JSON处理异常
     */
    public String getProjectContractDataAsChineseJsonDirect(String projectId) throws JsonProcessingException {
        // 1. 根据项目ID查询项目数据
        Project project = projectRepository.findById(projectId).orElse(null);
        if (project == null) {
            return "{}";
        }
        
        // 2. 根据项目ID查询合同数据
        List<Contract> contracts = contractRepository.findByProjectId(projectId);
        if (contracts == null || contracts.isEmpty()) {
            return "{}";
        }

        // 3. 获取合同ID列表
        List<String> contractIds = contracts.stream()
                .map(Contract::getId)
                .collect(Collectors.toList());

        // 4. 根据合同ID查询相关数据
        List<ContractLxPlan> contractLxPlans = contractLxPlanRepository.findByContractIdsGrouped(contractIds);
        List<ContractPaymoney> contractPaymoneys = contractpaymoneyRepository.findByContractIds(contractIds);
        List<Invoice> invoices = invoiceRepository.findByContractIdsGrouped(contractIds);
        List<Contractjxfpdj> contractjxfpdjs = contractjxfpdjRepository.findByContractIds(contractIds);

        // 5. 按合同ID对相关数据进行分组
        Map<String, List<ContractLxPlan>> lxPlansMap = contractLxPlans.stream()
                .collect(Collectors.groupingBy(ContractLxPlan::getParentID));
        Map<String, List<ContractPaymoney>> paymoneysMap = contractPaymoneys.stream()
                .collect(Collectors.groupingBy(ContractPaymoney::getContr_id_new));
        Map<String, List<Invoice>> invoicesMap = invoices.stream()
                .collect(Collectors.groupingBy(Invoice::getContr_id));
        Map<String, List<Contractjxfpdj>> jxfpdjsMap = contractjxfpdjs.stream()
                .collect(Collectors.groupingBy(Contractjxfpdj::getContract_id));

        // 6. 组装嵌套数据结构
        List<ProjectContractDataDTO.ContractDetail> contractDetails = contracts.stream()
                .map(contract -> new ProjectContractDataDTO.ContractDetail(
                        contract,
                        lxPlansMap.getOrDefault(contract.getId(), List.of()),
                        paymoneysMap.getOrDefault(contract.getId(), List.of()),
                        invoicesMap.getOrDefault(contract.getId(), List.of()),
                        jxfpdjsMap.getOrDefault(contract.getId(), List.of())
                ))
                .collect(Collectors.toList());

        // 7. 创建ProjectContractDataDTO对象 (在构造函数中进行字段过滤)
        ProjectContractDataDTO result = new ProjectContractDataDTO(project, contractDetails, contractDataQueryConfig);
        
        // 8. 返回中文JSON字符串
        return result.toChineseModelString();
    }

    /**
     * 获取项目合同数据的JSON格式，并通过大模型分析
     * @param projectId 项目ID
     * @return 分析结果
     * @throws JsonProcessingException JSON处理异常
     */
    public Flux<String> getProjectContractAnalysis(String projectId) throws JsonProcessingException {
//        ContractProjectDataDTO result = getProjectContractData(projectId);
        String modelString = getProjectContractDataAsChineseJsonDirect(projectId);
        if (modelString == null) {
            return Flux.just("未找到项目相关的合同数据");
        }

//        String modelString = result.toChineseModelString();

        return this.chatClient.prompt()
                .system(systemSpec -> systemSpec
                        .text("""
                                你是一名专业的合同智能分析助手，擅长从结构化合同数据中识别风险与合规问题。
                                
                                  你的任务是：
                                  1. 读取并理解用户提供的 JSON 格式合同数据。
                                  2. 按照用户的分析需求，从多个维度生成分析报告或可视化展示。
                                  3. 输出结果仅为一个 `<div>` 区块，可直接嵌入到上级页面中展示，无需页面交互逻辑。
                                
                                
                                请严格遵守以下规则：
                                1.  **角色定位**：以专业、严谨、客观的口吻进行汇报，避免主观臆测。
                                2.  **数据驱动**：所有结论必须有数据支撑，引用具体数值（如合同ID、节点名称、金额、日期等）。
                                3.  **结构化输出**：你的回答必须采用清晰的Html格式，包含标题、段落、列表和表格（如需要），确保可读性。
                                4.  **关注重点**：优先分析合同执行情况、资金流动、节点完成情况和风险预警。
                                5.  **提供建议**：在分析末尾，必须基于发现的问题提供具体、可操作的改进建议，而不是泛泛而谈。
                                6.  **输出要求**：
                                    6.1. 输出为标准的div块，所有 CSS 必须以内联 style 属性写在元素上，body样式不要使用body关键词，使用mybody。
                                    6.2. 页面整体风格简洁现代，采用浅色背景（#f9f9f9），深色标题（#2c3e50）。
                                    6.3. 报告标题居中显示，字号 26px，字体 Arial，字重 bold。
                                    6.4. 每个分析模块（如合同执行情况、资金流动等）请使用卡片式布局：
                                       - 白色背景
                                       - 圆角（8px）
                                       - 阴影（0 2px 6px rgba(0,0,0,0.1)）
                                       - 上下间距 20px
                                       - 内边距 15px
                                    6.5. 二级标题（h2）左侧带一条 4px 宽的蓝色边线（#3498db）。
                                    6.6. 表格使用隔行变色（浅灰色 #f2f2f2）并在鼠标 hover 时高亮。
                                    6.7. 输出时请只给出最终 HTML，不要包含推理过程。
                                
                                请首先确认理解上述指令。
                                """))
                .user(userSpec -> userSpec
                        .text("""
                                请基于以下合同数据，进行智能分析
                                分析重点包括：
                                   **相对方履行能力**：重点关注企查查数据中是否存在失信记录、公司信誉情况、工商信息、纳税信息、供应商黑名单，供应商画像、成立时间短、业务范围不符、注册地址异常、供应商成立时间不足 6 个月且合作金额较大（如超过 50 万元）、注册地址为 “虚拟地址”“民居”，或与多家其他供应商地址重复若未提供数据，请根据网络数据进行判断。
                                   **合同基础信息**：检查是否存在不合规现象（如合同倒置、金额异常、签约时间异常等）。
                                   **相对方、开票记录列表名称之间的关系图
                                **项目合同数据如下：**
                                ```json
                                {contractInfo}
                                ```
                                """)
                        .param("contractInfo", modelString))
                .stream()
                .content();
    }
    
    /**
     * 获取项目合同数据的JSON格式，并通过大模型分析（基于项目对象）
     * @param projectDTO 项目对象
     * @return 分析结果
     * @throws JsonProcessingException JSON处理异常
     */
    public Flux<String> getProjectContractAnalysis(ProjectDTO projectDTO) throws JsonProcessingException {
        ContractProjectDataDTO result = getProjectContractData(projectDTO);
        if (result == null) {
            return Flux.just("未找到项目相关的合同数据");
        }

        String modelString = result.toChineseModelString();

        return this.chatClient.prompt()
                .system(systemSpec -> systemSpec
                        .text("""
                                你是一名专业的合同智能分析助手，擅长从结构化合同数据中识别风险与合规问题。
                                
                                  你的任务是：
                                  1. 读取并理解用户提供的 JSON 格式合同数据。
                                  2. 按照用户的分析需求，从多个维度生成分析报告或可视化展示。
                                  3. 输出结果仅为一个 `<div>` 区块，可直接嵌入到上级页面中展示，无需页面交互逻辑。
                                
                                
                                请严格遵守以下规则：
                                1.  **角色定位**：以专业、严谨、客观的口吻进行汇报，避免主观臆测。
                                2.  **数据驱动**：所有结论必须有数据支撑，引用具体数值（如合同ID、节点名称、金额、日期等）。
                                3.  **结构化输出**：你的回答必须采用清晰的Html格式，包含标题、段落、列表和表格（如需要），确保可读性。
                                4.  **关注重点**：优先分析合同执行情况、资金流动、节点完成情况和风险预警。
                                5.  **提供建议**：在分析末尾，必须基于发现的问题提供具体、可操作的改进建议，而不是泛泛而谈。
                                6.  **输出要求**：
                                    6.1. 输出为标准的div块，所有 CSS 必须以内联 style 属性写在元素上，body样式不要使用body关键词，使用mybody。
                                    6.2. 页面整体风格简洁现代，采用浅色背景（#f9f9f9），深色标题（#2c3e50）。
                                    6.3. 报告标题居中显示，字号 26px，字体 Arial，字重 bold。
                                    6.4. 每个分析模块（如合同执行情况、资金流动等）请使用卡片式布局：
                                       - 白色背景
                                       - 圆角（8px）
                                       - 阴影（0 2px 6px rgba(0,0,0,0.1)）
                                       - 上下间距 20px
                                       - 内边距 15px
                                    6.5. 二级标题（h2）左侧带一条 4px 宽的蓝色边线（#3498db）。
                                    6.6. 表格使用隔行变色（浅灰色 #f2f2f2）并在鼠标 hover 时高亮。
                                    6.7. 输出时请只给出最终 HTML，不要包含推理过程。
                                
                                请首先确认理解上述指令。
                                """))
                .user(userSpec -> userSpec
                        .text("""
                                请基于以下合同数据，进行智能分析
                                分析重点包括：
                                   **相对方履行能力**：重点关注企查查数据中是否存在失信记录、公司信誉情况、工商信息、纳税信息、供应商黑名单，供应商画像、成立时间短、业务范围不符、注册地址异常、供应商成立时间不足 6 个月且合作金额较大（如超过 50 万元）、注册地址为 “虚拟地址”“民居”，或与多家其他供应商地址重复若未提供数据，请根据网络数据进行判断。
                                   **合同基础信息**：检查是否存在不合规现象（如合同倒置、金额异常、签约时间异常等）。
                                   **相对方、开票记录列表名称之间的关系图
                                **项目合同数据如下：**
                                ```json
                                {contractInfo}
                                ```
                                """)
                        .param("contractInfo", modelString))
                .stream()
                .content();
    }
    
    /**
     * 获取项目合同数据的JSON格式，并通过大模型分析（以项目作为最外层结构）
     * @param project 项目对象
     * @return 分析结果
     * @throws JsonProcessingException JSON处理异常
     */
    public Flux<String> getProjectContractAnalysisWithProjectAsRoot(Project project) throws JsonProcessingException {
        ProjectContractDataDTO result = getProjectContractDataWithProjectAsRoot(project);
        if (result == null) {
            return Flux.just("未找到项目相关的合同数据");
        }

        String modelString = result.toChineseModelString();

        return this.chatClient.prompt()
                .system(systemSpec -> systemSpec
                        .text("""
                                你是一名专业的合同智能分析助手，擅长从结构化合同数据中识别风险与合规问题。
                                
                                  你的任务是：
                                  1. 读取并理解用户提供的 JSON 格式合同数据。
                                  2. 按照用户的分析需求，从多个维度生成分析报告或可视化展示。
                                  3. 输出结果仅为一个 `<div>` 区块，可直接嵌入到上级页面中展示，无需页面交互逻辑。
                                
                                
                                请严格遵守以下规则：
                                1.  **角色定位**：以专业、严谨、客观的口吻进行汇报，避免主观臆测。
                                2.  **数据驱动**：所有结论必须有数据支撑，引用具体数值（如合同ID、节点名称、金额、日期等）。
                                3.  **结构化输出**：你的回答必须采用清晰的Html格式，包含标题、段落、列表和表格（如需要），确保可读性。
                                4.  **关注重点**：优先分析合同执行情况、资金流动、节点完成情况和风险预警。
                                5.  **提供建议**：在分析末尾，必须基于发现的问题提供具体、可操作的改进建议，而不是泛泛而谈。
                                6.  **输出要求**：
                                    6.1. 输出为标准的div块，所有 CSS 必须以内联 style 属性写在元素上，body样式不要使用body关键词，使用mybody。
                                    6.2. 页面整体风格简洁现代，采用浅色背景（#f9f9f9），深色标题（#2c3e50）。
                                    6.3. 报告标题居中显示，字号 26px，字体 Arial，字重 bold。
                                    6.4. 每个分析模块（如合同执行情况、资金流动等）请使用卡片式布局：
                                       - 白色背景
                                       - 圆角（8px）
                                       - 阴影（0 2px 6px rgba(0,0,0,0.1)）
                                       - 上下间距 20px
                                       - 内边距 15px
                                    6.5. 二级标题（h2）左侧带一条 4px 宽的蓝色边线（#3498db）。
                                    6.6. 表格使用隔行变色（浅灰色 #f2f2f2）并在鼠标 hover 时高亮。
                                    6.7. 输出时请只给出最终 HTML，不要包含推理过程。
                                
                                请首先确认理解上述指令。
                                """))
                .user(userSpec -> userSpec
                        .text("""
                                请基于以下合同数据，进行智能分析
                                分析重点包括：
                                   **相对方履行能力**：重点关注企查查数据中是否存在失信记录、公司信誉情况、工商信息、纳税信息、供应商黑名单，供应商画像、成立时间短、业务范围不符、注册地址异常、供应商成立时间不足 6 个月且合作金额较大（如超过 50 万元）、注册地址为 “虚拟地址”“民居”，或与多家其他供应商地址重复若未提供数据，请根据网络数据进行判断。
                                   **合同基础信息**：检查是否存在不合规现象（如合同倒置、金额异常、签约时间异常等）。
                                   **相对方、开票记录列表名称之间的关系图
                                **项目合同数据如下：**
                                ```json
                                {contractInfo}
                                ```
                                """)
                        .param("contractInfo", modelString))
                .stream()
                .content();
    }

    /**
     * 获取项目合同数据的原始JSON格式
     * @param projectId 项目ID
     * @return 项目合同数据的JSON字符串
     * @throws JsonProcessingException JSON处理异常
     */
    public String getProjectContractDataAsJson(String projectId) throws JsonProcessingException {
        ContractProjectDataDTO result = getProjectContractData(projectId);
        if (result == null) {
            return "{}";
        }
        return result.toModelString();
    }
    
    /**
     * 获取项目合同数据的原始JSON格式（基于项目对象）
     * @param projectDTO 项目对象
     * @return 项目合同数据的JSON字符串
     * @throws JsonProcessingException JSON处理异常
     */
    public String getProjectContractDataAsJson(ProjectDTO projectDTO) throws JsonProcessingException {
        ContractProjectDataDTO result = getProjectContractData(projectDTO);
        if (result == null) {
            return "{}";
        }
        return result.toModelString();
    }
    
    /**
     * 获取项目合同数据的原始JSON格式（以项目作为最外层结构）
     * @param project 项目对象
     * @return 项目合同数据的JSON字符串
     * @throws JsonProcessingException JSON处理异常
     */
    public String getProjectContractDataAsJsonWithProjectAsRoot(Project project) throws JsonProcessingException {
        ProjectContractDataDTO result = getProjectContractDataWithProjectAsRoot(project);
        if (result == null) {
            return "{}";
        }
        return result.toModelString();
    }

    /**
     * 获取项目合同数据的中文字段名JSON格式
     * @param projectId 项目ID
     * @return 项目合同数据的中文字段名JSON字符串
     * @throws JsonProcessingException JSON处理异常
     */
    public String getProjectContractDataAsChineseJson(String projectId) throws JsonProcessingException {
        ContractProjectDataDTO result = getProjectContractData(projectId);
        if (result == null) {
            return "{}";
        }
        return result.toChineseModelString();
    }
    
    /**
     * 获取项目合同数据的中文字段名JSON格式（基于项目对象）
     * @param projectDTO 项目对象
     * @return 项目合同数据的中文字段名JSON字符串
     * @throws JsonProcessingException JSON处理异常
     */
    public String getProjectContractDataAsChineseJson(ProjectDTO projectDTO) throws JsonProcessingException {
        ContractProjectDataDTO result = getProjectContractData(projectDTO);
        if (result == null) {
            return "{}";
        }
        return result.toChineseModelString();
    }
    
    /**
     * 获取项目合同数据的中文字段名JSON格式（以项目作为最外层结构）
     * @param project 项目对象
     * @return 项目合同数据的中文字段名JSON字符串
     * @throws JsonProcessingException JSON处理异常
     */
    public String getProjectContractDataAsChineseJsonWithProjectAsRoot(Project project) throws JsonProcessingException {
        ProjectContractDataDTO result = getProjectContractDataWithProjectAsRoot(project);
        if (result == null) {
            return "{}";
        }
        return result.toChineseModelString();
    }

}